package cn.funeralobjects.youtube.dl.extension.controller;

import cn.funeralobjects.youtube.dl.extension.service.DownloadService;
import cn.funeralobjects.youtube.dl.extension.utils.SpringUtils;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author FuneralObjects
 * Create date: 2020/4/5 12:19 AM
 */
@Component
@ServerEndpoint("/log/{id}/{format}")
public class LogController {
    private DownloadService downloadService;

    /**
     * 连接数
     */
    private static final AtomicInteger ONLINE = new AtomicInteger(0);
    private static final ExecutorService executorService;
    private static final AtomicInteger THREAD_INDEX = new AtomicInteger(0);

    static{
        executorService = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), r -> {
            Thread thread = new Thread(r);
            thread.setName("WS-LOG-THREAD-"+THREAD_INDEX.incrementAndGet());
            return thread;
        }, new ThreadPoolExecutor.AbortPolicy());
    }

    private Session session;
    private String id;
    private String format;


    @OnOpen
    public void onOpen(Session session,
                       @PathParam("id") String id,
                       @PathParam("format") String format){
        this.downloadService = SpringUtils.getBean(DownloadService.class);
        this.session = session;
        this.format = format;
        this.id = id;
        int online = ONLINE.incrementAndGet();
        System.out.println("A socket of log ["+id+"]["+format+"] online. \n Current Online:"+ online);
        startLog();
    }


    @OnClose
    public void onClose(){
        int online = ONLINE.decrementAndGet();
        System.out.println("A socket of log ["+this.id+"]["+this.format+"] offline. \n Current Online:"+ online);
    }

    private void startLog(){
        executorService.execute( () -> {
            String message;
            try {
                while ( (message = downloadService.getCurrentLog(id, format)) != null && this.session.isOpen() ){
                    this.sendMessage(message);
                    Thread.sleep(3000L);
                }
            } catch (IOException | InterruptedException e) {
                throw new RuntimeException(e);
            }finally {
                try {
                    this.session.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }
}
